//
//  ZJCircleView.swift
//  InfoAPP
//
//  Created by leeco on 2019/5/17.
//  Copyright © 2019 zsw. All rights reserved.
// 轮播图

import UIKit
import Kingfisher

// MARK: - Protocol
protocol ZJCircleViewDelegate: AnyObject {
    func circleView(_ circleView: ZJCircleView, didClickAtIndex index: Int)
}

// MARK: - Configuration
struct ZJCircleViewConfiguration {
    let autoScrollInterval: TimeInterval
    let pageControlHeight: CGFloat
    let titleLabelHeight: CGFloat
    let titleLabelMargin: CGFloat
    
    static let `default` = ZJCircleViewConfiguration(
        autoScrollInterval: 1.0,
        pageControlHeight: 20.0,
        titleLabelHeight: 30.0,
        titleLabelMargin: 10.0
    )
}

// MARK: - Data Model
struct ZJCircleViewItem {
    let image: Any // String(URL) or UIImage
    let title: String
    
    init(image: Any, title: String = "") {
        self.image = image
        self.title = title
    }
}

class ZJCircleView: UIView {
    
    // MARK: - Properties
    private var items: [ZJCircleViewItem] = []
    private var currentPage: Int = 0
    private var timer: Timer?
    private let configuration: ZJCircleViewConfiguration
    
    weak var delegate: ZJCircleViewDelegate?
    
    // MARK: - UI Components
    private lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.isPagingEnabled = true
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        scrollView.delegate = self
        scrollView.bounces = false
        scrollView.clipsToBounds = true
        return scrollView
    }()
    
    private lazy var pageControl: UIPageControl = {
        let pageControl = UIPageControl()
        pageControl.currentPageIndicatorTintColor = .white
        pageControl.pageIndicatorTintColor = UIColor.white.withAlphaComponent(0.5)
        pageControl.hidesForSinglePage = true
        pageControl.addTarget(self, action: #selector(pageControlValueChanged), for: .valueChanged)
        return pageControl
    }()
    
    private lazy var tapGesture: UITapGestureRecognizer = {
        let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        return gesture
    }()
    
    // MARK: - Initialization
    init(frame: CGRect, configuration: ZJCircleViewConfiguration = .default) {
        self.configuration = configuration
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        self.configuration = .default
        super.init(coder: coder)
        setupUI()
    }
    
    deinit {
        stopAutoScroll()
    }
    
    // MARK: - UI Setup
    private func setupUI() {
        backgroundColor = .clear
        
        addSubview(scrollView)
        addSubview(pageControl)
        
        scrollView.addGestureRecognizer(tapGesture)
        
        setupConstraints()
    }
    
    private func setupConstraints() {
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        pageControl.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
            
            pageControl.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            pageControl.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            pageControl.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0),
            pageControl.heightAnchor.constraint(equalToConstant: configuration.pageControlHeight)
        ])
    }
    
    // MARK: - Public Methods
    func configure(with items: [ZJCircleViewItem]) {
        self.items = items
        setupScrollView()
        setupPageControl()
        startAutoScroll()
    }
    
    func startAutoScroll() {
        guard items.count > 1 else { return }
        stopAutoScroll()
        
        timer = Timer.scheduledTimer(
            timeInterval: configuration.autoScrollInterval,
            target: self,
            selector: #selector(autoScroll),
            userInfo: nil,
            repeats: true
        )
    }
    
    func stopAutoScroll() {
        timer?.invalidate()
        timer = nil
    }
    
    func scrollToPage(_ page: Int, animated: Bool = true) {
        guard page >= 0 && page < items.count else { return }
        
        let targetPage = page
        let offset = CGPoint(x: bounds.width * CGFloat(targetPage), y: 0)
        scrollView.setContentOffset(offset, animated: animated)
    }
    
    // MARK: - Private Methods
    private func setupScrollView() {
        // 清除之前的子视图
        scrollView.subviews.forEach { $0.removeFromSuperview() }
        
        guard !items.isEmpty else { return }
        
        // 创建无限滚动的图片数组
        var infiniteItems = items
        
        // 在开头添加最后一张图片
        if let lastItem = items.last {
            infiniteItems.insert(lastItem, at: 0)
        }
        
        // 在结尾添加第一张图片
        if let firstItem = items.first {
            infiniteItems.append(firstItem)
        }

        
        items = infiniteItems
        
        // 创建图片视图
        for (index, item) in infiniteItems.enumerated() {
            let imageView = createImageView(for: item, at: index)
            scrollView.addSubview(imageView)
            
            // 添加标题标签
            if !item.title.isEmpty {
                let titleLabel = createTitleLabel(for: item, at: index)
                scrollView.addSubview(titleLabel)
            }
        }
        
        // 设置内容大小
        let contentWidth = bounds.width * CGFloat(infiniteItems.count)
        scrollView.contentSize = CGSize(width: contentWidth, height: bounds.height)
        
        // 设置初始位置（显示第一张真实图片）
        scrollView.setContentOffset(CGPoint(x: bounds.width, y: 0), animated: false)
        currentPage = 0
    }
    
    private func createImageView(for item: ZJCircleViewItem, at index: Int) -> UIImageView {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.frame = CGRect(
            x: bounds.width * CGFloat(index),
            y: 0,
            width: bounds.width,
            height: bounds.height
        )
        
        // 设置图片
        if let urlString = item.image as? String, let url = URL(string: urlString) {
            imageView.kf.setImage(
                with: url,
                placeholder: UIImage(named: "placeholder_image"),
                options: [
                    .transition(.fade(0.3)),
                    .cacheOriginalImage
                ]
            )
        } else if let image = item.image as? UIImage {
            imageView.image = image
        }
        
        return imageView
    }
    
    private func createTitleLabel(for item: ZJCircleViewItem, at index: Int) -> UILabel {
        let label = UILabel()
        label.text = item.title
        label.font = .systemFont(ofSize: 15, weight: .medium)
        label.textColor = .white
        label.numberOfLines = 2
        label.textAlignment = .left
        
        // 添加渐变背景
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [
            UIColor.clear.cgColor,
            UIColor.black.withAlphaComponent(0.4).cgColor
        ]
        gradientLayer.locations = [0.0, 1.0]
        label.layer.addSublayer(gradientLayer)
        
        label.frame = CGRect(
            x: bounds.width * CGFloat(index) + configuration.titleLabelMargin,
            y: bounds.height - configuration.titleLabelHeight - 8,
            width: bounds.width - configuration.titleLabelMargin * 2,
            height: configuration.titleLabelHeight
        )
        
        // 更新渐变层frame
        DispatchQueue.main.async {
            gradientLayer.frame = label.bounds
        }
        
        return label
    }
    
    private func setupPageControl() {
        pageControl.numberOfPages = items.count - 2
        pageControl.currentPage = 0
    }
    
    private func updateCurrentPage() {
        var page = Int(round(scrollView.contentOffset.x / bounds.width))
        
        if page == items.count - 1 {
            // 滚动到第倒数第二张张，跳转到第一张真实图片
            scrollView.setContentOffset(
                CGPoint(x: bounds.width, y: 0),
                animated: false
            )
            page = 1
        }

        currentPage = page;
        
        pageControl.currentPage = currentPage - 1
    }
    
    private func handleInfiniteScroll() {
        let page = Int(round(scrollView.contentOffset.x / bounds.width))
        
        if page == items.count - 1 {
            // 滚动到第倒数第二张张，跳转到第一张真实图片
            scrollView.setContentOffset(
                CGPoint(x: 0, y: 0),
                animated: false
            )
        } else if page == 0 {
            // 滚动到最后一张，跳转到第一张真实图片
            scrollView.setContentOffset(CGPoint(x: self.frameW * CGFloat(items.count - 1), y: 0), animated: false)
        }
    }
    
    // MARK: - Actions
    @objc private func autoScroll() {
        updateCurrentPage()//需要再调一下，滚动到的一帧，立即换成真实的位置
        
        let nextPage = currentPage + 1
        scrollToPage(nextPage >= items.count ? 0 : nextPage)
        
    }
    
    @objc private func pageControlValueChanged() {
        scrollToPage(pageControl.currentPage)
    }
    
    @objc private func handleTap() {
        delegate?.circleView(self, didClickAtIndex: currentPage)
    }
}

// MARK: - UIScrollViewDelegate
extension ZJCircleView: UIScrollViewDelegate {
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // 可以在这里添加滚动动画效果
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        handleInfiniteScroll()
        updateCurrentPage()
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        stopAutoScroll()
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        startAutoScroll()
    }
}
